package sup

import (
	"encoding/json"
	"fmt"

	"gitee.com/micro-plat/fas/modules/const/conf"
	"gitee.com/micro-plat/fas/modules/const/sql"
	"gitee.com/micro-plat/fas/modules/sp"
	"gitee.com/micro-plat/fas/modules/util"
	"github.com/asaskevich/govalidator"
	"github.com/micro-plat/hydra"
	"github.com/micro-plat/lib4go/types"
)

type IBilling interface {
	ChannelSync(param *ChannelInfoSync) (info types.XMap, err error)
	DownChannelPay(param *DownPay) (info types.XMap, err error)
	DownChannelRefund(param *DownRefund) (info types.XMap, err error)
	UpChannelPay(param *SupUpPay) (info types.XMap, err error)
	UpManualRecord(upChannelNo, changeTime string) (result string, err error)
	DownManualRecord(upChannelNo, changeTime string) (result string, err error)
	UpChannelRefund(param *UpRefund) (info types.XMap, err error)
	GetReportZeroBalance(channelNo, rptDate string) (result string, err error)
}

type Billing struct {
}

//NewBilling 获取对象
func NewBilling() (IBilling, error) {
	return &Billing{}, nil
}

//ChannelSync 渠道同步
func (b *Billing) ChannelSync(param *ChannelInfoSync) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("SupChannelSync:参数验证错误err:%+v,param:%+v", err, param)
	}
	param.CompanyID = types.GetString(param.CompanyID, conf.GetSupCompanyID())
	param.SystemID = types.GetString(param.SystemID, conf.GetSupSystemID())
	if param.CompanyID == "" || param.SystemID == "" {
		return nil, fmt.Errorf("SupChannelSync:CompanyID或者SystemID为空")
	}
	fmt.Printf("%+v\n", param)
	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}

	//3. 执行
	result, msg, err := sp.ExecuteSP(sql.SupChannelInfoSync, data)
	if err != nil {
		return nil, fmt.Errorf("SupChannelInfoSync调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result": result,
		"msg":    msg,
	}, nil
}

//DownChannelPay 下游渠道扣款
func (b *Billing) DownChannelPay(param *DownPay) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("SupDownChannelPay:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3. 执行
	result, msg, err := sp.ExecuteSP(sql.SupDownOrderPay, requestParam)
	if err != nil {
		return nil, fmt.Errorf("SupDownOrderPay调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result": result,
		"msg":    msg,
	}, nil
}

//DownChannelRefund 下游渠道退款
func (b *Billing) DownChannelRefund(param *DownRefund) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("SupDownChannelRefund:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3. 执行
	result, msg, err := sp.ExecuteSP(sql.SupDownOrderRefund, requestParam)
	if err != nil {
		return nil, fmt.Errorf("SupDownOrderRefund 调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result": result,
		"msg":    msg,
	}, nil
}

//UpChannelPay 上游渠道扣款
func (b *Billing) UpChannelPay(param *SupUpPay) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("SupUpChannelPay:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3. 执行
	result, msg, err := sp.ExecuteSP(sql.SupUpOrderPay, requestParam)
	if err != nil {
		return nil, fmt.Errorf("SupUpOrderPay 调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result": result,
		"msg":    msg,
	}, nil
}

//UpChannelRefund 上游渠道退款
func (b *Billing) UpChannelRefund(param *UpRefund) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("SupUpChannelRefund:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3. 执行
	result, msg, err := sp.ExecuteSP(sql.SupUpOrderRefund, requestParam)
	if err != nil {
		return nil, fmt.Errorf("SupUpOrderRefund 调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result": result,
		"msg":    msg,
	}, nil

}

//UpManualRecord sup查询记账系统上游的人工操作（加款/提款/红冲）账户记录
func (b *Billing) UpManualRecord(upChannelNo, changeTime string) (result string, err error) {
	//1. 验证参数
	if upChannelNo == "" || changeTime == "" {
		return "", fmt.Errorf("参数不可为空,upChannelNo:%s,changeTime:%s", upChannelNo, changeTime)
	}

	//2. 执行
	db, err := hydra.C.DB().GetDB(conf.DBName)
	if err != nil {
		return "", err
	}
	data, err := db.Query(sql.SupUpManualRecord, types.XMap{
		"up_channel_no": upChannelNo,
		"change_time":   changeTime,
	})
	if err != nil {
		return "", fmt.Errorf("SupUpManualRecord查询失败:%+v", err)
	}

	//3 返回值
	r, err := json.Marshal(data)
	return string(r), err
}

//DownManualRecord sup查询记账系统下游的人工操作（加款/提款/红冲）账户记录
func (b *Billing) DownManualRecord(downChannelNo, changeTime string) (result string, err error) {
	//1. 验证参数
	if downChannelNo == "" || changeTime == "" {
		return "", fmt.Errorf("参数不可为空,downChannelNo:%s,changeTime:%s", downChannelNo, changeTime)
	}

	//2. 执行
	db, err := hydra.C.DB().GetDB(conf.DBName)
	if err != nil {
		return "", err
	}
	data, err := db.Query(sql.SupDownManualRecord, types.XMap{
		"down_channel_no": downChannelNo,
		"change_time":     changeTime,
	})
	if err != nil {
		return "", fmt.Errorf("SupDownManualRecord查询失败:%+v", err)
	}

	r, err := json.Marshal(data)
	return string(r), err
}

//GetReportZeroBalance 获取零点余额
func (b *Billing) GetReportZeroBalance(channelNo, rptDate string) (result string, err error) {

	//1. 验证参数
	if channelNo == "" || rptDate == "" {
		return "", fmt.Errorf("参数不可为空,channelNo:%s,rptDate:%s", channelNo, rptDate)
	}
	//2. 执行
	db, err := hydra.C.DB().GetDB(conf.DBName)
	if err != nil {
		return "", err
	}
	data, err := db.Query(sql.GetSupReportZeroBalance, types.XMap{
		"channel_no": channelNo,
		"rpt_date":   rptDate,
	})
	if err != nil {
		return "", fmt.Errorf("SupReportZeroBalance查询失败:%+v", err)
	}

	if len(data) == 0 {
		return "", nil
	}

	//3 返回值
	r, err := json.Marshal(data.Get(0))
	return string(r), err
}
